package com.marchsoft.group.manager.security.config;

import com.marchsoft.group.manager.security.Filter.JwtAuthorizationTokenFilter;
import com.marchsoft.group.manager.security.handler.JwtAccessDeniedHandler;
import com.marchsoft.group.manager.security.handler.JwtAuthenticationEntryPointHandler;
import com.marchsoft.group.manager.security.handler.MyAuthenticationFailHandler;
import com.marchsoft.group.manager.security.handler.MyAuthenticationSuccessHandler;
import com.marchsoft.group.manager.security.service.JwtUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/**
 * fetch
 * @Author zhanghaoqi
 * @Description   SecurityConfig 配置类
 * @Data 19:29 2021/1/10
 * @return
 */

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启检验
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //登陆者信息
    @Autowired
   private JwtUserDetailsService jwtUserDetailsService;
    //认证失败信息返回
    @Autowired
   private JwtAuthenticationEntryPointHandler jwtAuthenticationEntryPointHandler;
    //用户权限不足信息返回
    @Autowired
   private JwtAccessDeniedHandler jwtAccessDeniedHandler;
    //token过滤器，用于token验证
    @Autowired
    private  JwtAuthorizationTokenFilter authenticationTokenFilter;
    //登陆成功后处理
    @Autowired
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
    //登陆失败后处理
    @Autowired
    private MyAuthenticationFailHandler myAuthenticationFailHandler;

    /**
     * fetch
     * @Author zhanghaoqi
     * @Description   验证登陆者的信息
     * @Data 15:39 2020/12/18
     * @param auth
     * @return void
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
    }
    /**
     * fetch
     * @Author zhanghaoqi
     * @Description  登陆者的密码加密方式
     * @Data 15:40 2020/12/18
     * @param
     * @return org.springframework.security.crypto.password.PasswordEncoder
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return  new BCryptPasswordEncoder();
    }

    /**
     * fetch
     * @Author zhanghaoqi
     * @Description  资源拦截
     * @Data 16:38 2020/12/18
     * @param httpSecurity
     * @return void
     */
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception{
                    httpSecurity.formLogin()
//                           .loginProcessingUrl("/login")
                            .successHandler(myAuthenticationSuccessHandler)
                            .failureHandler(myAuthenticationFailHandler)
                            .and()
                            .authorizeRequests()
                            //不需验证即可访问的请求
//                            .antMatchers("/aaa").permitAll()
//                           .antMatchers("/login").permitAll()
                            //swagger
                            .antMatchers("/swagger-ui.html").permitAll()
                            .antMatchers("/swagger-resources/**").permitAll()
                            .antMatchers("/webjars/**").permitAll()
                            .antMatchers("/*/api-docs").permitAll()
                            //是为了方便后面写前后端分离的时候前端过来的第一次验证请求，这样做，会减少这种请求的时间和资源使用
                            .antMatchers(HttpMethod.OPTIONS,"/**").permitAll()
                            //其余请求都得验证通过后才能访问
                            .anyRequest().authenticated()
                            .and()
                            //授权异常
                            .exceptionHandling()
                            //登陆验证失败
                            .authenticationEntryPoint(jwtAuthenticationEntryPointHandler)
                            //权限拦截器，提示用户没有当前权限
                            .accessDeniedHandler(jwtAccessDeniedHandler)
                            .and()
                            //关闭csrf防护
                            .csrf().disable()
                            //关闭session策略，没有jwt时使用session存储用户信息，我们使用jwt，所以不使用session
                            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
                    //在UsernamePasswordAuthenticationFilter前添加一个过滤器，来判断是否有token。
                    httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
    }

}
